﻿// -------------------------------------------------------------------------
//    @FileName         :    BagSystemTestBase.h
//    @Author           :    gaoyi
//    @Date             :    2025/1/20
//    @Email            :    445267987@qq.com
//    @Module           :    BagSystemTestBase
//
// -------------------------------------------------------------------------

#pragma once

#include <gtest/gtest.h>
#include <memory>
#include <vector>
#include <unordered_map>
#include <random>

// 包含必要的框架头文件
#include "NFComm/NFCore/NFPlatform.h"
#include "NFComm/NFPluginModule/NFCheck.h"
#include "NFComm/NFShmStl/NFShmVector.h"
#include "NFComm/NFShmStl/NFShmHashMap.h"

// 包含背包系统相关头文件
#include "NFLogicCommon/NFItemDefine.h"
#include "NFLogicCommon/NFItemCreator.h"
#include "NFServerLogic/NFLogicServer/NFLogicServerPlayerPlugin/Bag/NFServicePackage.h"
#include "NFServerLogic/NFLogicServer/NFLogicServerPlayerPlugin/Bag/NFBagPage.h"
#include "NFServerLogic/NFLogicServer/NFLogicServerPlayerPlugin/Bag/BagPageOp/NFBagPageOpMgr.h"
#include "NFServerLogic/NFLogicServer/NFLogicServerPlayerPlugin/Bag/BagPageOp/NFBagPageOp.h"
#include "NFServerLogic/NFLogicServer/NFLogicServerPlayerPlugin/Bag/NFPackageUtil.h"

// 包含物品描述相关头文件
#include "ResStore/DescStore/ItemDesc.h"
#include "MockItemDesc.h"

// 前向声明
class NFPlayer;
class NFBagPage;
class NFBagPageOp;
class NFBagPageOpMgr;

/**
 * @brief 背包系统测试基类
 * 
 * 为所有背包系统测试提供公共的测试环境和工具函数
 * 包括模拟数据创建、测试工具函数、断言辅助函数等
 */
class BagSystemTestBase : public ::testing::Test {
public:
    BagSystemTestBase();
    virtual ~BagSystemTestBase();

protected:
    // 测试生命周期管理
    virtual void SetUp() override;
    virtual void TearDown() override;
    
    // 静态设置，在所有测试前运行一次
    static void SetUpTestSuite();
    static void TearDownTestSuite();

protected:
    // === 测试数据创建工具 ===
    
    /**
     * @brief 创建测试用的玩家对象
     * @param playerId 玩家ID
     * @param playerName 玩家名称
     * @return 玩家对象指针
     */
    NFPlayer* CreateTestPlayer(uint64_t playerId = 1001, const std::string& playerName = "TestPlayer");
    
    /**
     * @brief 创建测试用的物品
     * @param itemId 物品ID
     * @param count 物品数量
     * @param quality 物品品质
     * @param bind 是否绑定
     * @return 物品对象
     */
    NFGridItem CreateTestItem(int itemId, int count = 1, int quality = 1, bool bind = false);
    
    /**
     * @brief 创建测试用的装备
     * @param equipId 装备ID
     * @param quality 装备品质
     * @param level 装备等级
     * @return 装备对象
     */
    NFGridItem CreateTestEquip(int equipId, int quality = 1, int level = 1);
    
    /**
     * @brief 创建测试用的背包页面
     * @param bagType 背包类型
     * @param maxGrid 最大格子数
     * @return 背包页面对象指针
     */
    NFBagPage* CreateTestBagPage(int bagType, int maxGrid = 50);
    
    /**
     * @brief 创建测试用的背包操作管理器
     * @param player 玩家对象
     * @param reason 操作原因
     * @param needCommit 是否需要提交
     * @return 背包操作管理器对象指针
     */
    NFBagPageOpMgr* CreateTestBagOpMgr(NFPlayer* player, int reason = 1, bool needCommit = true);

protected:
    // === 测试验证工具 ===
    
    /**
     * @brief 验证背包页面状态
     * @param bagPage 背包页面
     * @param expectedUsedCount 期望使用的格子数
     * @param expectedEmptyCount 期望空闲的格子数
     */
    void VerifyBagPageState(NFBagPage* bagPage, int expectedUsedCount, int expectedEmptyCount);
    
    /**
     * @brief 验证物品属性
     * @param item 物品对象
     * @param expectedId 期望物品ID
     * @param expectedCount 期望数量
     * @param expectedQuality 期望品质
     */
    void VerifyItemProperties(const NFGridItem& item, int expectedId, int expectedCount, int expectedQuality);
    
    /**
     * @brief 验证背包中是否包含指定物品
     * @param bagPage 背包页面
     * @param itemId 物品ID
     * @param expectedCount 期望数量
     * @return 是否包含指定数量的物品
     */
    bool VerifyItemInBag(NFBagPage* bagPage, int itemId, int expectedCount);
    
    /**
     * @brief 验证金钱数量
     * @param player 玩家对象
     * @param moneyType 金钱类型
     * @param expectedAmount 期望金钱数量
     */
    void VerifyMoneyAmount(NFPlayer* player, int moneyType, int64_t expectedAmount);

protected:
    // === 测试辅助工具 ===
    
    /**
     * @brief 填充背包到指定容量
     * @param bagPage 背包页面
     * @param itemId 物品ID
     * @param count 要填充的格子数
     */
    void FillBagToCapacity(NFBagPage* bagPage, int itemId, int count);
    
    /**
     * @brief 清空背包
     * @param bagPage 背包页面
     */
    void ClearBag(NFBagPage* bagPage);
    
    /**
     * @brief 获取随机物品ID
     * @return 随机物品ID
     */
    int GetRandomItemId();
    
    /**
     * @brief 获取随机数量
     * @param min 最小值
     * @param max 最大值
     * @return 随机数量
     */
    int GetRandomCount(int min = 1, int max = 100);
    
    /**
     * @brief 生成测试用的物品ID列表
     * @param count 物品种类数量
     * @return 物品ID列表
     */
    std::vector<int> GenerateTestItemIds(int count);

protected:
    // === 常量定义 ===
    
    // 测试用物品ID
    static constexpr int TEST_ITEM_NORMAL = 10001;      // 普通物品
    static constexpr int TEST_ITEM_EQUIP = 20001;       // 装备
    static constexpr int TEST_ITEM_CONSUMABLE = 30001;  // 消耗品
    static constexpr int TEST_ITEM_MATERIAL = 40001;    // 材料
    static constexpr int TEST_ITEM_STACKABLE = 50001;   // 可堆叠物品
    static constexpr int TEST_ITEM_UNIQUE = 60001;      // 唯一物品
    
    // 测试用背包类型
    static constexpr int TEST_BAG_TYPE_NORMAL = 0;      // 普通背包
    static constexpr int TEST_BAG_TYPE_EQUIP = 1;       // 装备背包
    static constexpr int TEST_BAG_TYPE_MATERIAL = 2;    // 材料背包
    static constexpr int TEST_BAG_TYPE_STORAGE = 3;     // 仓库
    
    // 测试用金钱类型
    static constexpr int TEST_MONEY_TYPE_GOLD = 1;      // 金币
    static constexpr int TEST_MONEY_TYPE_SILVER = 2;    // 银币
    static constexpr int TEST_MONEY_TYPE_DIAMOND = 3;   // 钻石
    
    // 测试用操作原因
    static constexpr int TEST_REASON_SYSTEM = 1;        // 系统给予
    static constexpr int TEST_REASON_QUEST = 2;         // 任务奖励
    static constexpr int TEST_REASON_SHOP = 3;          // 商店购买
    static constexpr int TEST_REASON_TRADE = 4;         // 交易获得

protected:
    // === 成员变量 ===
    
    // 测试用对象
    static MockItemDesc* s_mockItemDesc;
    std::unique_ptr<NFPlayer> m_testPlayer;
    std::vector<std::unique_ptr<NFBagPage>> m_testBagPages;
    std::vector<std::unique_ptr<NFBagPageOpMgr>> m_testBagOpMgrs;
    
    // 随机数生成器
    std::random_device m_randomDevice;
    std::mt19937 m_randomGen;
    
    // 测试计数器
    int m_testCounter;
    
    // 测试标志
    bool m_setupCompleted;
    bool m_teardownCompleted;
};

// 测试用的宏定义
#define ASSERT_ITEM_VALID(item) \
    ASSERT_FALSE((item).IsEmpty()) << "物品不应该为空"

#define ASSERT_ITEM_EMPTY(item) \
    ASSERT_TRUE((item).IsEmpty()) << "物品应该为空"

#define ASSERT_BAG_ITEM_COUNT(bagPage, itemId, expectedCount) \
    do { \
        int actualCount = 0; \
        for (int i = 0; i < (bagPage)->GetMaxGrid(); ++i) { \
            const NFGridItem* item = (bagPage)->GetItem(i); \
            if (item && item->GetItemID() == (itemId)) { \
                actualCount += item->GetNumber(); \
            } \
        } \
        ASSERT_EQ(actualCount, (expectedCount)) << "背包中物品数量不符合预期"; \
    } while(0)

#define ASSERT_BAG_USED_COUNT(bagPage, expectedCount) \
    ASSERT_EQ((bagPage)->GetUsedGridCount(), (expectedCount)) << "背包使用格子数不符合预期"

#define ASSERT_BAG_EMPTY_COUNT(bagPage, expectedCount) \
    ASSERT_EQ((bagPage)->GetEmptyGridCount(), (expectedCount)) << "背包空闲格子数不符合预期" 